<?php
/**
 * Created by PhpStorm.
 * @author Sojo
 * Date: 2016/6/25
 * Time: 20:07
 */
namespace App\Http\Admin\User\Models;

use Framework\BaseClass\Http\Admin\Model;
use App\Eloquent\Admin\Role;
use App\Eloquent\Admin\RoleMenu;
use App\Eloquent\Admin\RoleUser;

class Permission extends Model
{
    public function getRoleList()
    {
        return Role::all();
    }

    public function getRoleListByRoleAssignment($userId)
    {
        $roleUserIds = RoleUser::where('admin_user_id', $userId)->get()->pluck('admin_role_id')->toArray();

        $roleList = Role::all();

        foreach ($roleList as $key => $role) {
            $role->permission = (in_array($role->id, $roleUserIds)) ? 1 : 0;
            $role->user_id = $userId;
        }

        return $roleList;
    }

    public function saveRoleAssignment($userId, $roleId)
    {
        $roleUser = RoleUser::withTrashed()->firstOrNew([
            'admin_user_id' => $userId,
            'admin_role_id' => $roleId
        ]);

        if ($roleUser->id && !$roleUser->deleted_at) xThrow(ERR_LOGIC_DATA_NEED_TO_UPDATE);

        $oldRoleUser = RoleUser::where('admin_user_id', $userId)->first();
        $oldRoleUser->delete();

        return ($roleUser->id) ? $roleUser->restore() : $roleUser->save();
    }

    public function addRole($name, $displayName, $description)
    {
        $role = new Role();
        $saveData = [
            'name'         => $name,
            'display_name' => $displayName,
            'description'  => $description
        ];

        return $this->saveRole($role, $saveData);
    }

    public function updateRole($roleId, $name, $displayName, $description)
    {
        $role = Role::firstOrNew(['id' => $roleId]);
        if (!$role->id) xThrow(ERR_LOGIC_NO_DATA_EXIST);
        if ($role->name == $name && $role->display_name == $displayName && $role->description == $description)
            xThrow(ERR_LOGIC_DATA_NEED_TO_UPDATE);
        $saveData = [
            'name'         => $name,
            'display_name' => $displayName,
            'description'  => $description
        ];

        return $this->saveRole($role, $saveData);
    }

    private function saveRole(Role $role, array $saveData)
    {
        $role->fill($saveData);
        return $role->save();
    }

    public function delRole($roleId)
    {
        $role = Role::find($roleId);
        if (!$role) xThrow(ERR_LOGIC_NO_DATA_EXIST);
        return $role->delete();
    }

    public function singleSavePermissionAssignment($roleId, $menuId, $permission)
    {
        $roleMenu = RoleMenu::withTrashed()->firstOrNew([
            'admin_role_id' => $roleId,
            'admin_menu_id' => $menuId
        ]);

        $result = false;
        if ((bool)$permission) {
            if ($roleMenu->id && !$roleMenu->deleted_at) xThrow(ERR_LOGIC_DATA_NEED_TO_UPDATE);

            if ($roleMenu->id) {
                $result = $roleMenu->restore();
            } else {
                $result = $roleMenu->save();
            }
        } else {
            if (!$roleMenu->id || ($roleMenu->id && $roleMenu->deleted_at)) xThrow(ERR_LOGIC_DATA_NEED_TO_UPDATE);

            if ($roleMenu->id) $result = $roleMenu->delete();
            $result = $result > 0 ? true : false;
        }

        return $result;
    }

    public function multiSavePermissionAssignment($roleId, $params)
    {
        $roleMenuIds = RoleMenu::withTrashed()
            ->where('admin_role_id', $roleId)
            ->get()
            ->pluck('admin_menu_id')
            ->toArray();

        // 过滤权限状态为禁止和不存在于角色菜单表中的菜单
        foreach ($params as $key => $param) {
            if (!(bool)$param->permission && !in_array($param->id, $roleMenuIds)) {
                unset($params[$key]);
            }
        }

        $result = [];
        foreach ($params as $param) {
            try {
                $result[] = $this->singleSavePermissionAssignment($roleId, $param->id, $param->permission);
            } catch (\DebugError $e) {
                continue;
            }
        }

        return !in_array(false, $result) ? true : false;
    }
}